﻿using Inaction.Business.Security;
using Inaction.ServiceContract;
using Inaction.Security;
using System;
using System.Linq;

namespace Inaction.Extensions.Security
{
    [Serializable]
    internal class SecurityProvider : ISecurityProvider
    {
        private static string ParaFix
        {
            get { return DbProvider.Instance.ParaFix; }
        }

        public SecurityProvider()
        {
            
        }
        public Inaction.Security.Principal Login()
        {
            InitAdmin();
            var identity = Inaction.Security.Principal.Instance.Identity;
            string sql = Mapping.EntitySqlStatement.GetSelectSql<UserInfo>();
            sql += @" Where "
                + UserInfo.NumberProperty.Column.FormatName + " = " + ParaFix + UserInfo.NumberProperty.Name
                + @" And "
                + UserInfo.PasswordProperty.Column.FormatName + " = " + ParaFix + UserInfo.PasswordProperty.Name
                + @" And "
                + UserInfo.DeletedProperty.Column.FormatName + " = " + ParaFix + UserInfo.DeletedProperty.Name;
            using (var command = DbProvider.CreateCommand(sql))
            {
                DbProvider.AddParameter(command, UserInfo.NumberProperty.Name, identity.UserNumber);
                DbProvider.AddParameter(command, UserInfo.PasswordProperty.Name, identity.Token);
                DbProvider.AddParameter(command, UserInfo.DeletedProperty.Name, false);
                var reader = command.ExecuteReader();
                if (reader.Read())
                {
                    var user = new UserInfo();
                    user.Init(reader);
                    Inaction.Security.Principal.Instance = new SecurityPrincipal(user);
                }
                return Inaction.Security.Principal.Instance;
            }
        }

        public string ChangePassword(string userNumber, string oldPassword, string newPassword)
        {
            var oldPwd = DEncrypt.MakeHashSalt(oldPassword);
            var user = UserInfo.Single(p => p.Name == userNumber && p.Password == oldPwd);
            if (user == null)
            {
                return "给定的用户不存在或用户名密码不对应!";
            }
            user.Password = DEncrypt.MakeHashSalt(newPassword);
            user.Save();
            return string.Empty;
        }

        public void CheckIdentity()
        {
            var userIdentity = Inaction.Security.Principal.Instance.Identity;
            if (userIdentity == null)
            {
                throw new Exception(Inaction.Resource.Properties.Resources.NotLogin);
            }
            var token = DEncrypt.AESEncrypt(userIdentity.UserNumber, Inaction.AppConfig.Instance.CrypKey);
            if (userIdentity.Token.Length != token.Length)
            {
                throw new Exception(Inaction.Resource.Properties.Resources.NoCertificationRequest);
            }
            for (int i = 0; i < token.Length; i++)
            {
                if (!token[i].Equals(userIdentity.Token[i]))
                {
                    throw new Exception(Inaction.Resource.Properties.Resources.NoCertificationRequest);
                }
            }
        }

        public static void InitAdmin()
        {
            string tableName = UserInfo.ClassInfo.Table.FormatName;
            string sql = @"Select Count(*) From " + tableName
                + " Where " + UserInfo.NumberProperty.Column.FormatName + " = 'admin';";
            using (var command = DbProvider.CreateCommand(sql))
            {
                if (command.ExecuteScalar().ToString().Equals("0"))
                {
                    sql = @"Insert Into " + tableName + "(" +
                        UserInfo.IdProperty.Column.FormatName + ","
                        + UserInfo.NumberProperty.Column.FormatName + ","
                        + UserInfo.NameProperty.Column.FormatName + ","
                        + UserInfo.PasswordProperty.Column.FormatName + ","
                        + UserInfo.UserTypeProperty.Column.FormatName + ","
                        + UserInfo.DeletedProperty.Column.FormatName + ","
                        + UserInfo.CreateTimeProperty.Column.FormatName + ","
                        + UserInfo.UpdateTimeProperty.Column.FormatName
                        + ") Values ("
                        + ParaFix + UserInfo.IdProperty.Column.Name + ","
                        + ParaFix + UserInfo.NumberProperty.Column.Name + ","
                        + ParaFix + UserInfo.NameProperty.Column.Name + ","
                        + ParaFix + UserInfo.PasswordProperty.Column.Name + ","
                        + ParaFix + UserInfo.UserTypeProperty.Column.Name + ","
                        + ParaFix + UserInfo.DeletedProperty.Column.Name + ","
                        + ParaFix + UserInfo.CreateTimeProperty.Column.Name + ","
                        + ParaFix + UserInfo.UpdateTimeProperty.Column.Name + ")";
                    command.CommandText = sql;
                    DbProvider.AddParameter(command, UserInfo.IdProperty.Column.Name, Util.Sequence.NewId);
                    DbProvider.AddParameter(command, UserInfo.NumberProperty.Column.Name, "admin");
                    DbProvider.AddParameter(command, UserInfo.NameProperty.Column.Name, "管理员");
                    DbProvider.AddParameter(command, UserInfo.PasswordProperty.Column.Name, DEncrypt.MakeHashSalt("admin"));
                    DbProvider.AddParameter(command, UserInfo.UserTypeProperty.Column.Name,Inaction.Util.TypeConvert.ConvertToDbValue(UserType.Admin));
                    DbProvider.AddParameter(command, UserInfo.DeletedProperty.Column.Name, false);
                    DbProvider.AddParameter(command, UserInfo.CreateTimeProperty.Column.Name, DateTime.Now);
                    DbProvider.AddParameter(command, UserInfo.UpdateTimeProperty.Column.Name, DateTime.Now);
                    var result = command.ExecuteNonQuery();
                }
            }
        }
    }
}